﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using OmronLib.Base;

namespace OmronLib
{
    public abstract class OmronBase : IDisposable
    {
        public virtual void Open(int timeout = 3000) { }
        public virtual void Open(string Ip,int Port,int timeout = 3000) { }
        public virtual void Close() { }
        protected virtual void CheckResponse(byte[] bytes) { }
        public List<T> GetData<T>(List<byte> datas)
        {
            List<T> result = new List<T>();
            if (typeof(T) == typeof(bool))
            {
                foreach (byte b in datas)
                {
                    dynamic tmp = b == 0x01;
                    result.Add(tmp);
                }
            }
            else if (typeof(T) == typeof(string))
            {
                dynamic tmp = Encoding.ASCII.GetString(datas.ToArray());
                result.Add(tmp);
            }
            else
            {
                int size = Marshal.SizeOf<T>();
                Type bitConverter = typeof(BitConverter);
                System.Reflection.MethodInfo[] methods = bitConverter.GetMethods(System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Static);
                System.Reflection.MethodInfo? method = methods.FirstOrDefault(m => m.ReturnType == typeof(T) && m.GetParameters().Length == 2);
                if (method == null)
                    throw new Exception("Can't Find Any Convert suitable for this case");

                for (int i = 0; i < datas.Count; i += size)
                {
                    List<byte> arr = datas.GetRange(i, size);
                    if (BitConverter.IsLittleEndian)
                        arr.Reverse();
                    result.Add((T)method.Invoke(bitConverter, new object[] { arr.ToArray(), 0 }));
                }
            }
            return result;
        }

        public List<byte> GetBytes<T>(params T[] datas)
        {
            List<byte> result = new List<byte>();
            if (typeof(T) == typeof(bool))
            {
                for (int i = 0; i < datas.Length; i++)
                {
                    byte tmp = (byte)(bool.Parse(datas[i].ToString()) ? 0x01 : 0x00);
                    result.Add(tmp);
                }
            }
            else if (typeof(T) == typeof(string))
            {
                byte[] buff = Encoding.ASCII.GetBytes(datas[0].ToString());
                result.AddRange(buff);
            }
            else
            {
                foreach (var data in datas)
                {
                    dynamic tmp = data;
                    byte[] buff = BitConverter.GetBytes(tmp);
                    if (BitConverter.IsLittleEndian)
                        buff = buff.Reverse().ToArray();
                    result.AddRange(buff);
                }
            }
            return result;
        }

        public string FCS(string cmd)
        {
            byte[] b = Encoding.ASCII.GetBytes(cmd);
            byte xorResult = b[0];
            for (int i = 1; i < b.Length; i++)
            {
                xorResult ^= b[i];
            }

            return xorResult.ToString("X2");
        }

        public void Dispose()
        {
            this.Close();
        }
    }
}
